﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;

namespace Klinkby.PipesAndFilters
{
    public class SplitterFilter<TIn, TOut> : IFilter<TIn, TOut[]>
    {
        IFilter<TIn, TOut>[] _filters;

        public SplitterFilter(params IFilter<TIn, TOut>[] filters)
        {
            if (filters == null)
                throw new ArgumentNullException("filters");
            _filters = filters;
        }

        public static SplitterFilter<TIn, TOut> Create(params IFilter<TIn, TOut>[] filters)
        {
            return new SplitterFilter<TIn, TOut>(filters);
        }

        public TOut[] Process(TIn value)
        {
            // TODO Use ParallelEnumerable in .NET 4
            return /*Parallel*/Enumerable.Range(0, _filters.Length)
                                         .Select(
                                            i => _filters[i].CanProcess(value)
                                            ? _filters[i].Process(value)
                                            : default(TOut)).ToArray();
        }

        public bool CanProcess(TIn value)
        {
            return _filters.Any(f => f.CanProcess(value));
        }

        #region Dispose
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                foreach(var f in _filters)
                    f.Dispose();
            }
        }
        public void Dispose()
        {
            GC.SuppressFinalize(this);
            Dispose(true);
        }
        ~SplitterFilter()
        {
            Dispose(false);
        }
        #endregion
    }
}
